<template>
  <!-- 角色管理  -->
  <div class="menu-page">
    <div id="role-manage">
      <div class="role-manage-body">
        <div class="rm-org">
          <el-tree
              :data="orgs"
              :props="{label:'empty',children:'children'}"
              @node-click="clickNode"
              accordion
              highlight-current
          >
            <template #default="{ node, data }">
              <span>{{ data.empty.name }}</span>
            </template>
          </el-tree>
        </div>
        <div class="rm-data">
          <el-table
              :data="roles"
          >
            <!--            <el-table-column type="selection" width="55"/>-->
            <el-table-column label="角色" prop="name"/>
            <el-table-column label="键" prop="roleKey"/>
            <el-table-column fixed="right" label="操作" width="200px">
              <template #default="ctx">
                <div>
                  <el-button link type="primary" icon="RoleIcon" size="small" @click="openAuth(ctx.row)"/>
                  <el-button link type="warning" icon="Edit" size="small" @click="editOpt(ctx.row)"/>
                  <el-popconfirm title="是否删除?"
                                 @confirm="deleteRole(ctx.row,ctx.index)"
                  >
                    <template #reference>
                      <el-button link type="danger" icon="Delete" size="small"/>
                    </template>
                  </el-popconfirm>
                </div>
              </template>
            </el-table-column>
          </el-table>
          <el-button @click="openAdd" link type="primary" style="width: 100%;margin-bottom: 10px;margin-top: 10px">
            新增
          </el-button>
          <div>
            <Pages ref="rolePage" @action="paging" @change="changeSize"/>
          </div>
        </div>
      </div>
    </div>
    <el-dialog
        title="新增角色"
        v-model="addFlag"
        width="20%"
        draggable
        @close="closeAdd"
    >
      <el-form :model="roleEmpty" label-position="left" label-width="50px" ref="addRoleFormRef" :rules="addRule">
        <el-form-item label="角色" prop="name">
          <el-input v-model="roleEmpty.name"/>
        </el-form-item>
        <el-form-item label="键" prop="roleKey">
          <el-input v-model="roleEmpty.roleKey"/>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button type="primary" size="small" @click="addRole(addRoleFormRef)">确认</el-button>
      </template>
    </el-dialog>
    <el-dialog
        v-model="authflag"
        draggable
        width="40%"
        title="权限管理"
        @close="closeRoleAuth"
    >
      <el-tabs
          v-model="activeName"
          @tab-change="tabChange"
      >
        <!--      @tab-click="tabClick"    -->
        <el-tab-pane class="auth-tabs" name="menu_auth" label="菜单权限">
          <div style="height: 100%;display: flex;flex-direction: column;justify-content: space-between">
            <div>
              <el-tree
                  :data="menu_tree"
                  ref="menuAuthTreeRef"
                  node-key="id"
                  show-checkbox
                  :default-checked-keys="menuArr"
                  @check-change="checkMenu"
                  check-strictly
              >
                <template #default="scope">
                  {{ scope.data.empty.title }}
                </template>
              </el-tree>
            </div>
            <div style="display: flex;flex-direction: row-reverse;justify-content: center">
              <el-button type="primary" @click="saveMenuRoleAuth">保存</el-button>
            </div>
          </div>

        </el-tab-pane>

        <el-tab-pane class="auth-tabs" name="func_auth" label="功能权限">
          <div style="width: 100%;height: 100%;display: flex;flex-direction: column;justify-content: center">
            <div style="width: 100%;display: flex;flex-direction: row;justify-content: center">
              <el-transfer
                  :data="func_list"
                  v-model="funcArr"
                  :titles="['待授权','已授权']"
                  :button-texts="['撤回', '授权']"
                  filterable
                  filter-placeholder="查找"
                  :filter-method="funcSelect"
                  @change="funcChange"
                  @right-check-change="rightFuncCheck"
              >
                <template #default="{option}">
                  <el-tooltip :content="option.method+''+option.path" placement="right">
                    {{option.name}}
                  </el-tooltip>
                </template>
              </el-transfer>
            </div>
            <div style="display: flex;flex-direction: row-reverse;justify-content: center">
              <el-button type="primary" @click="saveFuncRoleAuth">保存</el-button>
            </div>
          </div>
        </el-tab-pane>
      </el-tabs>
      <template #footer>
        <!--        <el-button @click="authflag=!authflag">关闭</el-button>-->
      </template>
    </el-dialog>
    <el-dialog
        v-model="editflag"
        title="编辑"
        width="20%"
        draggable
    >
      <el-form label-position="left" label-width="50px">
        <el-form-item label="名称">
          <el-input v-model="editForm.name"/>
        </el-form-item>
        <el-form-item label="键">
          <el-input v-model="editForm.roleKey"/>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button type="primary" @click="executeEdit">保存</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import {onMounted, onUnmounted, reactive, ref} from "vue";
import Axios from "../../../../plugins/axios";
import {userStore} from "../../../../store/user";
import {sys} from "../../../../model/system";
import Pages from "../../../../management-system/components/Pages.vue";
import event from "../../../../plugins/event";
import {ElMessage, FormInstance, FormRules, TabPaneName} from "element-plus";
import {UpdateOrgAndRoleEvent} from "../../../../plugins/evenKey";
import {del} from "@vue/composition-api";

const user = userStore()
const orgs = ref<any>([])
const roles = ref<any>([])
const rolePage = ref()
const addFlag = ref(false)
const menu_tree = ref<any[]>([])
const selectRole = ref(0)
const func_list=ref([])

const menuAuthTreeRef = ref()

const prop = {
  children: 'children',
  label: 'empty',
}

const editflag = ref(false)
const editForm = ref({
  id: 0,
  name: '',
  roleKey: ''
})

function editOpt(row) {
  editForm.value = {
    id: row.id,
    name: row.name,
    roleKey: row.roleKey
  }
  editflag.value = !editflag.value
}

// 调用编辑接口
function executeEdit() {
  editflag.value = !editflag.value
}


const authflag = ref(false)
// menuArr 所选编辑角色菜单授权信息
const menuArr = ref<number[]>([])
const menuArrBak=ref<number[]>([])
// funcArr 所选编辑角色功能权限信息
const funcArr = ref<number[]>([])
// 功能权限备份 用于计算功能授权改变后的差集
const funcArrBak=ref<number[]>([])

async function openAuth(row) {
  authflag.value = !authflag.value
  selectRole.value = row.id
  // 根据选项卡 选择对应的函数初始化当前  授权卡的初始化操作
  menu_tree.value=await loadMenuAuth()
  menuArr.value=await loadRoleMenuAuth()
  menuArrBak.value=[...menuArr.value]

  func_list.value=await loadFuncAuth()
  funcArr.value=await loadRoleFuncAuth()
  funcArrBak.value=[...funcArr.value]
}

// 查询当前操作角色可授权菜单列表
function loadMenuAuth():Promise<any> {
  return new Promise<any>(resolve=>{
    Axios.get('/api/configuration/menu/role/tree', {
      params: {
        orgId: user.userInfo.org,
        roleId: user.userInfo.role
      }
    }).then(rep => {
      let data = rep.data
      if (data.code === "0000") {
        let anx1 = anx(data.data);
        resolve(anx1)
      }
    }).then(err=>{
      resolve([])
    })
  })
}

// 查询当前选中角色已授权菜单信息
function loadRoleMenuAuth() :Promise<any>{
  return new Promise<any>(resolve=>{
    Axios.get('/api/configuration/role/menu/list', {
      params: {
        roleId: selectRole.value
      }
    }).then(response => {
      let data: sys.Result<any> = response.data
      if (data.code === '0000') {
        let ids:number[]=[]
        data.data.forEach(item => {
          ids.push(item.id)
        })
        resolve(ids)
      }else{
        resolve([])
      }
    }).catch(err=>{
      console.log(err)
      resolve([])
    })
  })
}

// 查询当前登录角色可授权功能列表
function loadFuncAuth() {
  return new Promise<any>((resolve, reject) => {
    //初始化功能列表信息
    Axios.get('/api/configuration/func/role/list', {
      params: {
        orgId: user.userInfo.org,
        roleId: user.userInfo.role
      }
    }).then(response => {
      let data: sys.Result<sys.FuncRouter[]> = response.data
      if (data.code === '0000') {
        let anxFunc = anx_func(data.data);
        resolve(anxFunc)
      }else {
        resolve([])
      }
    }).catch(err=>{
      console.log(err)
      resolve([])
    })
  })
}

// 查询当前选中角色已授权功能列表
function loadRoleFuncAuth() {
  return new Promise<any>((resolve, reject) => {
      Axios.get('/api/configuration/role/func/list',{
        params:{
          roleId:selectRole.value
        }
      }).then(response=>{
        let data:sys.Result<sys.FuncRouter[]> =response.data
        if (data.code==='0000'){
          let anxFunc = anx_func(data.data);
          let keys:number[]=[]
          anxFunc.forEach(item=>{
            keys.push(item.id)
          })
          resolve(keys)
        }else {
          resolve([])
        }
      }).catch(err=>{
        console.log(err)
        resolve([])
      })
  })
}

// 功能列表过滤
function funcSelect (query, item) {
  if (!query) return true
  if (query==='') return true
  return item.name.startsWith(query)
}

async function funcChange(keys,direction) {
  if (direction==='left'){
    // 超级管理员权限禁止变更
    if (selectRole.value===1){
      funcArr.value=await loadRoleFuncAuth()
      ElMessage({
        type:'warning',
        message:'禁止操作'
      })
      return
    }
  }
}

function rightFuncCheck(keys) {

}


function closeRoleAuth() {
  menu_tree.value=[]
  menuArr.value=[]
  func_list.value=[]
  funcArr.value=[]
}

async function checkMenu(data, flag) {
  //  超级管理员角色 不允许操作变更权限
  if (selectRole.value===1&& !flag){
    menuAuthTreeRef.value.setChecked(data,true,true)
    ElMessage({
      type:'warning',
      message:'禁止操作'
    })
  }
}

// 授权选项卡
const activeName = ref('menu_auth')

// 选项卡切换初始化选项卡数据
async function tabChange(name: TabPaneName) {
  // 初始化菜单授权信息
  if (name === 'menu_auth') {
    // 初始化加载菜单信息  根据当前操作人的组织和角色 加载他可以给 选中的角色授权的菜单列表(不是每个人都可以随便授权整个菜单,只能授权自己拥有的菜单权限)
    menu_tree.value=await loadMenuAuth()
    menuArr.value=await loadRoleMenuAuth()
    menuArrBak.value=[...menuArr.value]
  }

  // 初始功能权限
  if (activeName.value === 'func_auth') {
    func_list.value=await loadFuncAuth()
    funcArr.value=await loadRoleFuncAuth()
    funcArrBak.value=[...funcArr.value]
  }
}

// 保存菜单授权
function saveMenuRoleAuth() {
  if (selectRole.value===1){
    ElMessage({
      type:'warning',
      message:'禁止操作'
    })
    return
  }
  if (selectRole.value===user.userInfo.role){
    ElMessage({
      type:'warning',
      message:'禁止操作'
    })
    return
  }
  // 获取当前所有选中
  let checkedKeys:any[] = []
  // getCheckedNodes 需要包含半选中节点状态
  let checkedNodes = menuAuthTreeRef.value.getCheckedNodes(false,true);
  checkedNodes.forEach(item=>{
    checkedKeys.push(item.id)
  })
  console.log('checkedKeys:',checkedKeys)

  // 计算当前被选中数组中 不存在于原来权限中的key 表示新增权限
  let addKeys = checkedKeys.filter(item=>{
    return !menuArrBak.value.includes(item);
  });
  console.log('addKeys:',addKeys)

  // 过滤掉新keys
  let subKeys = checkedKeys.filter(item=>{
    return !addKeys.includes(item)
  });
  console.log('subKeys:',subKeys)

  // 计算备份数据中的元素 在当前选中数组中不存在的元素 表示被删除的权限
  let delKeys = menuArrBak.value.filter(item=>{
    return !subKeys.includes(item);
  });

  console.log('delKeys:',delKeys)

  if (addKeys.length>0){
    Axios.post('/api/configuration/role/auth/menu/add',{
      menus:addKeys,
      roleId:selectRole.value
    }).then(async (response)=>{
      let data:sys.Result<any> =response.data
      if (data.code==='0000'){
       // 刷新初始渲染
        menuArr.value=[]
        menu_tree.value=await loadMenuAuth()
        console.log("add: menu_true:",menu_tree.value)
        menuArr.value=await loadRoleMenuAuth()
        console.log("add: menuArr:",menuArr.value)
        menuArrBak.value=[...menuArr.value]

        ElMessage({
          type:'success',
          message:'权限更新成功'
        })
      }
    })
  }

  if (delKeys.length>0){
    Axios.post('/api/configuration/role/auth/menu/del',{
      menus:delKeys,
      roleId:selectRole.value
    }).then(async (response)=>{
      let data:sys.Result<any> =response.data
      if (data.code==='0000'){
        // 刷新初始渲染
        menuArr.value=[]
        menu_tree.value=await loadMenuAuth()
        console.log("del: menu_true:",menu_tree.value)

        menuArr.value=await loadRoleMenuAuth()
        console.log("del: menuArr:",menuArr.value)
        menuArrBak.value=[...menuArr.value]
        ElMessage({
          type:'success',
          message:'权限更新成功'
        })
      }else {
        menuArr.value=[]
        menu_tree.value=await loadMenuAuth()
        console.log("del: menu_true:",menu_tree.value)

        menuArr.value=await loadRoleMenuAuth()
        console.log("del: menuArr:",menuArr.value)
        menuArrBak.value=[...menuArr.value]
      }
    })
  }

}

// 保存功能授权
function saveFuncRoleAuth() {
  if (selectRole.value===1){
    ElMessage({
      type:'warning',
      message:'禁止操作'
    })
    return
  }
  if (selectRole.value===user.userInfo.role){
    ElMessage({
      type:'warning',
      message:'禁止操作'
    })
    return
  }

  // 获取当前授权id
  console.log('funcs:',funcArr.value)
  // 计算当前新授权id
  let addKeys = funcArr.value.filter(item=>{
    return !funcArrBak.value.includes(item)
  });
  console.log('func add:',addKeys)

  // 计算待删除id
  // 删除 待授权id
  let subKeys = funcArr.value.filter(item=>{
    return !addKeys.includes(item)
  });
  console.log('func sub:',subKeys)

  let delKeys = funcArrBak.value.filter(item=>{
    return !subKeys.includes(item)
  });
  console.log('func del:',delKeys)

  if (addKeys.length>0){
    Axios.post('/api/configuration/role/auth/func/add',{
      roleId:selectRole.value,
      funcs:addKeys
    }).then(async (response)=>{
      let data:sys.Result<any> =response.data
      funcArr.value=[]
      if (data.code==='0000'){
        func_list.value=await loadFuncAuth()
        funcArr.value=await loadRoleFuncAuth()
        funcArrBak.value=[...funcArr.value]
        ElMessage({
          type:'success',
          message:'权限更新成功'
        })
      }else {
        func_list.value=await loadFuncAuth()
        funcArr.value=await loadRoleFuncAuth()
        funcArrBak.value=[...funcArr.value]
      }
    })
  }

  if (delKeys.length>0){
    Axios.post('/api/configuration/role/auth/func/del',{
      roleId:selectRole.value,
      funcs:delKeys
    }).then(async (response)=>{
      let data:sys.Result<any> =response.data
      funcArr.value=[]
      if (data.code==='0000'){
        func_list.value=await loadFuncAuth()
        funcArr.value=await loadRoleFuncAuth()
        funcArrBak.value=[...funcArr.value]
        ElMessage({
          type:'success',
          message:'权限更新成功'
        })
      }else {
        func_list.value=await loadFuncAuth()
        funcArr.value=await loadRoleFuncAuth()
        funcArrBak.value=[...funcArr.value]
      }
    })
  }

}


const roleEmpty = ref({
  name: '',
  roleKey: ''
})

// 初始化当前选择的组织为 角色当前操作组织
const selectOrg = ref()

function clickNode(node) {
  selectOrg.value = node.empty.id
  let size = rolePage.value.GetSize()
  Axios.get('/api/configuration/org/role/list',
      {
        params: {
          orgId: selectOrg.value,
          // 每次切换节点重新加载
          page: 1,
          size: size,
        }
      }
  ).then(response => {
    let result: sys.Result<any> = response.data
    if (result.code === "0000") {
      roles.value = result.data.rows
      rolePage.value.SetTotal(result.data.count)
    }
  })
}


const addRoleFormRef = ref<FormInstance>()

function checkNull(rule: any, value: any, callback: any) {
  if (value === '') {
    callback(new Error('必填'))
  } else {
    callback()
  }
}

const addRule = reactive<FormRules>({
  name: [{validator: checkNull, trigger: 'blur'}],
  roleKey: [{validator: checkNull, trigger: 'blur'}],
})

function closeAdd() {
  addRoleFormRef.value?.resetFields()
}

function openAdd() {
  // 组织添加角色 没有 0 id的组织 默认阻止添加
  if (selectOrg.value < 1) {
    ElMessage({
      type: 'warning',
      message: '请选择组织进行添加'
    })
    return
  }
  roleEmpty.value = {
    name: '',
    roleKey: ''
  }
  addFlag.value = !addFlag.value
}

function addRole(formEl: FormInstance | undefined) {
  if (!formEl) return
  formEl.validate((flag) => {
    if (flag) {
      let size: number = rolePage.value.GetSize()
      let page: number = rolePage.value.GetPageNum()
      let orgId: number = selectOrg.value
      Axios.post('/api/configuration/org/add/role', {
        orgId: selectOrg.value,
        name: roleEmpty.value.name,
        roleKey: roleEmpty.value.roleKey
      }).then(response => {
        let data: sys.Result<any> = response.data
        if (data.code === '0000') {
          if (data.msg !== '') {
            ElMessage({
              type: 'success',
              message: data.msg
            })
          }
          // todo 操作成功 重新加载数据
          Axios.get("/api/configuration/org/role/list", {
            params: {
              orgId: orgId,
              page: page,
              size: size,
            }
          }).then(function (response) {
            let result: sys.Result<any> = response.data
            if (result.code === "0000") {
              roles.value = result.data.rows
              rolePage.value.SetTotal(result.data.count)
            }
          })
        }
      })
      addFlag.value = !addFlag.value
    } else {
      ElMessage({
        type: 'warning',
        message: '请填写信息'
      })
    }
  })
}

function deleteRole(row, index) {
  let size: number = rolePage.value.GetSize()
  let page: number = rolePage.value.GetPageNum()
  let orgId: number = selectOrg.value
  Axios.post('/api/configuration/org/del/role', {
    id: row.id
  }).then(response => {
    let result: sys.Result<any> = response.data
    if (result.code === "0000") {
      if (result.msg !== '') {
        ElMessage({
          type: 'success',
          message: result.msg
        })
      }
      // todo 操作成功 重新加载数据
      Axios.get("/api/configuration/org/role/list", {
        params: {
          orgId: orgId,
          page: page,
          size: size,
        }
      }).then(function (response) {
        let result: sys.Result<any> = response.data
        if (result.code === "0000") {
          roles.value = result.data.rows
          rolePage.value.SetTotal(result.data.count)
        }
      })
    }
  })
}

function paging(newPage, size) {
  // 执行翻页
  let orgId: number = selectOrg.value
  Axios.get("/api/configuration/org/role/list", {
    params: {
      orgId: orgId,
      page: newPage,
      size: size,
    }
  }).then(function (response) {
    let result: sys.Result<any> = response.data
    if (result.code === "0000") {
      roles.value = result.data.rows
      rolePage.value.SetTotal(result.data.count)
    }
  })
}

function changeSize(page: number, size: number) {
  let orgId: number = selectOrg.value
  Axios.get("/api/configuration/org/role/list", {
    params: {
      orgId: orgId,
      page: page,
      size: size,
    }
  }).then(function (response) {
    let result: sys.Result<any> = response.data
    if (result.code === "0000") {
      roles.value = result.data.rows
      rolePage.value.SetTotal(result.data.count)
    }
  })
}

// 把被包裹的树信息解析到当前属性中,便于 el-tree的解析
function anx(arr: any[]): any[] {
  let tree: any[] = []
  arr.forEach(item => {
    let obj = {...item, ...item.empty}
    let c = anx(obj.children)
    obj.children = c
    tree.push(obj)
  })
  return tree
}

function anx_func(arr:any[]):any[] {
  // let list:any[]=[]
  arr.forEach(item=>{
    item.key=item.id
    item.label=item.name
  })
  return arr
}

function init() {
  selectOrg.value = user.userInfo.org
  Axios.get("/api/configuration/org/list", {
    params: {
      org: selectOrg.value
    }
  }).then(function (response) {
    let data = response.data
    if (data.code === "0000") {
      orgs.value = data.data
    }
  })
  let size = rolePage.value.GetSize()
  Axios.get('/api/configuration/org/role/list',
      {
        params: {
          orgId: selectOrg.value,
          page: 1,
          size: size,
        }
      }
  ).then(response => {
    let result: sys.Result<any> = response.data
    if (result.code === "0000") {
      roles.value = result.data.rows
      rolePage.value.SetTotal(result.data.count)
    }
  })
}

event.on(UpdateOrgAndRoleEvent, init)
onMounted(init)
onUnmounted(() => {
  event.off(UpdateOrgAndRoleEvent, init)
})


</script>


<style scoped>
#role-manage {
  width: 100%;
  display: flex;
  flex-direction: row;
  justify-content: center;
}

.role-manage-body {
  width: 97%;
  margin: auto;
  height: 800px;
  display: flex;
  flex-direction: row;
  justify-content: space-between;
}

.rm-org {
  width: 20%;
  box-shadow: var(--el-box-shadow-light);
  background-color: white;
}

.rm-data {
  width: 79%;
  box-shadow: var(--el-box-shadow-light);
  background-color: white;
}

.auth-tabs {
  width: 100%;
  height: 400px;
  overflow-y: auto;
}
</style>